#include "camera.h"

camera::camera(void)
{
	Position = ViewDirection = RightVector = UpVector = 0;
	InitCamera();
}

void camera::InitCamera()
{
	if(Position != 0)
	{
		delete Position;
		delete ViewDirection;
		delete RightVector;
		delete UpVector;
	}
	//Init with standard OGL values:
	Position = new Vertex3f (0.0, 0.0, 10);
	ViewDirection = new Vertex3f( 0.0, 0.0, -1.0);
	RightVector = new Vertex3f (1.0, 0.0, 0.0);
	UpVector = new Vertex3f (0.0, 1.0, 0.0);

	//Only to be sure:
	Xrot = Yrot = Zrot = 0.0;
}

void camera::SetCamera()
{
	//as we know the up vector, we can easily use gluLookAt:
	gluLookAt(Position->X, Position->Y, Position->Z,
		Position->X + ViewDirection->X, Position->Y + ViewDirection->Y, Position->Z + ViewDirection->Z,
		UpVector->X, UpVector->Y, UpVector->Z);
}

void camera::Move(Vertex3f *movement)
{
	Position->Add(movement);
}


void camera::RotateX(float xrot)
{
	Xrot += xrot;
	//Rotate viewdir around the right vector:
	//ViewDir = Normalize3dVector(ViewDir*cos(xrot*PIdiv180) + UpVector * sin(xrot * PIdiv180));
	Vertex3f *result1 = ViewDirection->Multpli(cos(xrot * PIdiv180));
	Vertex3f *result2 = UpVector->Multpli(sin(xrot * PIdiv180));
	result1->Add(result2);
	result1->Normalize();
	delete ViewDirection;
	delete result2;
	ViewDirection = result1;

	//now compute the new UpVector (by cross product)
	//UpVector = CrossProduct(&ViewDir, &RightVector) * -1;
	result1 = ViewDirection->CrossProduct(RightVector);
	delete UpVector;
	UpVector = result1->Multpli(-1);
	delete result1;
}

void camera::RotateY(float yrot)
{
	Yrot += yrot;
	//Rotate viewdir around the right vector:
	//ViewDir = Normalize3dVector(ViewDir*cos(Angle*PIdiv180) - RightVector*sin(Angle*PIdiv180));
	float value = cos(yrot * PIdiv180);
	Vertex3f *result1 = ViewDirection->Multpli(cos(yrot * PIdiv180));
	Vertex3f *result2 = RightVector->Multpli(sin(yrot * PIdiv180));
	result1->Subtract(result2);
	result1->Normalize();
	delete ViewDirection;
	delete result2;
	ViewDirection = result1;

	//now compute the new RightVector (by cross product)
	//RightVector = CrossProduct(&ViewDir, &UpVector);
	result1 = ViewDirection->CrossProduct(UpVector);
	delete RightVector;
	RightVector = result1;
}

void camera::RotateZ(float zrot)
{
	Xrot += zrot;
	//Rotate viewdir around the right vector:
	//RightVector = Normalize3dVector(RightVector*cos(Angle*PIdiv180) + UpVector*sin(Angle*PIdiv180));
	Vertex3f *result1 = RightVector->Multpli(cos(zrot * PIdiv180));
	Vertex3f *result2 = UpVector->Multpli(sin(zrot * PIdiv180));
	result1->Add(result2);
	result1->Normalize();
	delete RightVector;
	delete result2;
	RightVector = result1;

	//now compute the new UpVector (by cross product)
	//UpVector = CrossProduct(&ViewDir, &RightVector) * -1;
	result1 = ViewDirection->CrossProduct(RightVector);
	delete UpVector;
	UpVector = result1->Multpli(-1);
	delete result1;
}


void camera::MoveForward(float distance)
{
	//Position = Position + (ViewDir * -Distance);
	Vertex3f *result1 = ViewDirection->Multpli(-distance);
	Position->Add(result1);
	delete result1;
}

void camera::MoveUpward(float distance)
{
	//Position = Position + (UpVector * Distance);
	Vertex3f *result1 = UpVector->Multpli(distance);
	Position->Add(result1);
	delete result1;
}

void camera::StrafeRight (float distance)
{
	//Position = Position + (RightVector * Distance);
	Vertex3f *result1 = RightVector->Multpli(distance);
	Position->Add(result1);
	delete result1;
}

camera::~camera(void)
{
	delete Position;
	delete ViewDirection;
	delete RightVector;
	delete UpVector;
}
